/** 
Copyright (c) 2010, Sheikh Abdul Wahid Ahmed
Details @ http://extremecodeworld.codeplex.com/license
**/

using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Reflection;
using System.IO;
using Microsoft.CSharp;
using System.Text;

namespace EXtremecode.Utils
{
	/// <summary>
	/// Summary description for AssemblyCreator.
	/// </summary>
	public class AssemblyCreator
	{
		public static Assembly CreateAssembly(string sourceFileName
             , string[] referencedAssemblies)
		{
			return CreateAssembly(sourceFileName,referencedAssemblies,string.Empty); 
		}

		public static  Assembly CreateAssembly(StringBuilder sourceCode
             , string[] referencedAssemblies)
		{
			return  CreateAssembly(sourceCode, referencedAssemblies,string.Empty); 
		}

        public static Assembly CreateAssembly(StringBuilder sourceCode
           , string[] referencedAssemblies
             , string outputAssemblyName)
        {
            if (!DataEncryptor.IsGeneratingAllowed)
            {
                Logging.Logger.Write("UnRegistered");
                return null;
            }

            CSharpCodeProvider cscp = new CSharpCodeProvider();
            CompilerParameters compparams = new CompilerParameters();


            //set properties
            compparams.GenerateExecutable = false;
            if (!string.IsNullOrEmpty(outputAssemblyName))
            {
                compparams.GenerateInMemory = false;
                compparams.OutputAssembly = outputAssemblyName;
            }
            else
            {
                compparams.GenerateInMemory = true;
            }


            //referenced assembly
            if (referencedAssemblies != null)
            {
                foreach (string referencedAssembly in referencedAssemblies)
                {
                    compparams.ReferencedAssemblies.Add(referencedAssembly);
                }
            }


            //creating assembly
            CompilerResults compresult = cscp.CompileAssemblyFromSource(compparams, sourceCode.ToString());

            //error handling
            if (compresult == null || compresult.Errors.Count > 0)
            {
                System.Text.StringBuilder sb = new System.Text.StringBuilder();
                if (compresult != null)
                {
                    for (int i = 0; i < compresult.Output.Count; i++)
                        sb.Append(compresult.Output[i] + Environment.NewLine);
                    for (int i = 0; i < compresult.Errors.Count; i++)
                        sb.Append(i.ToString() + ": " + compresult.Errors[i].ToString() + Environment.NewLine);
                }
                else
                {
                    sb.Append("Compilation Faild");
                }
                throw Logging.Logger.Write(new Exception(sb.ToString()));

            }

            return compresult.CompiledAssembly;

        }
		public static  Assembly CreateAssembly(string sourceFileName
             , string[] referencedAssemblies
            ,string outputAssemblyName)
		{
			StringBuilder sourceCode;
			
			//Open file stream and load file contents on string builder.
			FileStream fStream;
			try
			{
				fStream=new FileStream(sourceFileName,FileMode.Open); 
			}
			catch(Exception ex)
			{
				throw Logging.Logger.Write(string.Format("Unable to open the the file '{0}'",sourceFileName),ex);
			}
			sourceCode=FileUtil.ReadStreamData(fStream);

			return CreateAssembly(sourceCode,referencedAssemblies,outputAssemblyName);

		}

	}
}
